<template>
	<div :class="{
      'message-audio': true,
      'reserve': props.messageItem.flow === 'out',
    }" @click="toggleClick">
		<div class="audio-icon-container">
			<div :class="{ 'mask': true, 'play': isAudioPlaying }" />
			<Icon class="icon" width="15px" height="20px" :file="audioIcon" />
		</div>
		<div class="time" :style="{ width: `${props.content.second * 5}px` }">
			{{ props.content.second || 1 }} "
		</div>
	</div>
</template>

<script lang="ts" setup>
	import { onUnmounted, ref, watch } from 'vue';
	import { IMessageModel } from '@tencentcloud/chat-uikit-engine';
	import Icon from './../Icon.vue';
	import audioIcon from '@/im/static/img/msg-audio.svg';

	interface IProps {
		broadcastNewAudioSrc : string;
		messageItem : IMessageModel;
		content : any;
	}

	interface IEmits {
		(
			e : 'getGlobalAudioContext',
			map : Map<string, any>,
			options ?: { newAudioSrc : string }
		) : void;
	}

	const emits = defineEmits<IEmits>();
	const props = withDefaults(defineProps<IProps>(), {
		messageItem: () => ({}) as IMessageModel,
		content: () => ({}) as any,
	});

	const audioMap = new Map<string, any>();
	const isAudioPlaying = ref<boolean>(false);

	onUnmounted(() => {
		const audioContext = getAudio();
		if (isAudioPlaying.value) {
			stopAudio();
		}
		audioContext?.destroy?.();
		audioMap.delete('audio');
	});

	watch(() => props.broadcastNewAudioSrc, (newSrc) => {
		if (newSrc !== props.content.url && isAudioPlaying.value) {
			stopAudio();
			// 这一步的 audioContext 大概率已被销毁 手动执行一下暂停
			// The audioContext may have been destroyed. Manually execute the pause
			isAudioPlaying.value = false;
		}
	});

	function toggleClick() {
		emits('getGlobalAudioContext', audioMap, { newAudioSrc: props.content.url });
		if (props.messageItem.hasRiskContent || !props.content.url) {
			uni.$wdToast.error('暂不支持播放')
			return;
		}
		// audioContext 会被缓存 必须拉取一次
		// audioContext will be cached, it must be get first
		const audioContext = getAudio();
		if (!audioContext) {
			audioMap.set('audio', uni.createInnerAudioContext() as any);
			// #ifdef MP
			uni.setInnerAudioOption({
				obeyMuteSwitch: false,
			});
			// #endif
			initAudioSrc();
		}
		toggleAudioPlayState();
	}

	function toggleAudioPlayState() {
		if (!isAudioPlaying.value) {
			playAudio();
		} else {
			stopAudio();
		}
	}

	function initAudioSrc() {
		const audioContext = getAudio();
		if (!audioContext) {
			return;
		}
		audioContext.src = props.content.url;
		isAudioPlaying.value = false;
		audioContext.onPlay(onAudioPlay);
		audioContext.onStop(onAudioStop);
		audioContext.onEnded(onAudioEnded);
		audioContext.onError(onAudioError);
	}

	function playAudio() {
		const audioContext = getAudio();
		if (!audioContext) {
			return;
		}
		audioContext.play();
	}

	function stopAudio() {
		const audioContext = getAudio();
		if (!audioContext) {
			return;
		}
		try {
			// audiocontext 的内存对象还在 但可能播放实例已被销毁
			// The memory of the audiocontext is in memory. But The play instance may have been destroyed.
			audioContext.stop();
		} catch {
			// ignore
		}
	}

	function onAudioPlay() {
		isAudioPlaying.value = true;
	}

	function onAudioStop() {
		isAudioPlaying.value = false;
	}

	function onAudioEnded() {
		isAudioPlaying.value = false;
	}

	function onAudioError() {
		console.warn('audio played error');
	}

	function getAudio() : any | undefined {
		return audioMap.get('audio');
	}
</script>

<style lang="scss" scoped>
	$flow-in-bg-color: #fbfbfb;
	$flow-out-bg-color: #dceafd;

	:not(not) {
		display: flex;
		flex-direction: column;
		box-sizing: border-box;
		min-width: 0;
	}

	.message-audio {
		flex-direction: row;
		flex: 0 0 auto;
		cursor: pointer;
		-webkit-tap-highlight-color: transparent;
		overflow: hidden;

		.audio-icon-container {
			// uniapp中会有一些偏差 这里 width 要比图标略宽
			width: 16px;
			height: 20px;
			position: relative;
			flex: 0 0 auto;
			flex-direction: row;
			justify-content: flex-end;
			margin: 0 7px 0 0;
			overflow: hidden;

			.mask {
				position: absolute;
				z-index: 1;
				width: 105%;
				height: 105%;
				left: 0;
				top: 0;
				transform-origin: right;
				transform: scaleX(0);
				background-color: $flow-in-bg-color;

				&.play {
					animation: audio-play 2s steps(1, end) infinite;
				}
			}
		}

		@keyframes audio-play {
			0% {
				transform: scaleX(0.7056);
			}

			50% {
				transform: scaleX(0.3953);
			}

			75% {
				transform: scaleX(0);
				visibility: hidden;
			}

			100% {
				transform: scaleX(0);
				visibility: hidden;
			}
		}

		.time {
			max-width: 165px;
			min-width: 20px;
			text-align: start;
			white-space: nowrap;
		}

		&.reserve {
			flex-direction: row-reverse;

			.time {
				text-align: end;
			}

			.audio-icon-container {
				margin: 0 0 0 7px;

				.mask {
					transform-origin: left;
					background-color: $flow-out-bg-color;
				}
			}

			.icon {
				transform: rotate(180deg);
			}
		}
	}
</style>